﻿/*
 * Copyright 2012 Rene Prost, Registrite ja Infosüsteemide Keskus 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;

using Xtee.Core.Envelope;
using System.IO;
using Calculator.Xroad.Eu.Headers;
using Calculator.Xroad.Eu.Messages;
using Metadata.Xroad.Eu.Messages;
using Xtee.Core.Envelope.Header;

namespace Xtee.Core.Test
{
    [TestFixture]
    public class SoapEnvelopeTests
    {
        /*1. if header is missing then body should be present*/
        /*2. if header is present when nimi element must be present and body also*/

        [Test]
        public void TestListMethods()
        {
            var serializer = new XteeSerializer();
            var mss = new MemoryStream(File.ReadAllBytes(@"../../ResourceData/listMethods.xml"));

            var envelope = serializer.Deserialize<SoapEnvelope>(mss);
            Assert.That(envelope.Body, Is.Not.Null);
            Assert.That(envelope.Body is ListMethods, Is.True);

        }
        
        [Test]
        public void BasicEnvelopeTest()
        {
            string xml = @"
    <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' 
                   xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
                   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
                   xmlns:xroad='http://x-road.eu/xsd/xroad.xsd'
                   xmlns:id = 'http://x-road.eu/xsd/identifiers'
                   xmlns:tns='http://calculator.x-road.eu'>
    <SOAP-ENV:Header>
        <xroad:client id:objectType='SUBSYSTEM'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>generic-consumer</id:subsystemCode>
        </xroad:client>
        <xroad:service id:objectType='SERVICE'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:serviceCode>Add</id:serviceCode>
        </xroad:service>
        <xroad:id>411d6755661409fed365ad8135f8210be07613da</xroad:id>
        <xroad:protocolVersion>4.0</xroad:protocolVersion>
    </SOAP-ENV:Header>
        <SOAP-ENV:Body>
            <tns:Add> 
            </tns:Add>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope> 
            ";

            XteeSerializer serializer = new XteeSerializer();
            MemoryStream mss = new MemoryStream(Encoding.UTF8.GetBytes(xml));

            var envelope = serializer.Deserialize<SoapEnvelope>(mss);
            Assert.IsNotNull(((AddInputHeader)envelope.Header).Service.ServiceCode);
            Assert.IsNull(((AddInputHeader)envelope.Header).Service.SubsystemCode);
            
        }

        [ExpectedException(ExpectedMessage = "Couldn't find meta information of operation [ETTeavitus]", MatchType = MessageMatch.Contains)]
        [Test]
        public void ShouldFailIfMetaNotFound()
        {
            string xml = @"
    <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' 
                   xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
                   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
                   xmlns:xroad='http://x-road.eu/xsd/xroad.xsd'
                   xmlns:id = 'http://x-road.eu/xsd/identifiers'
                   xmlns:tns='http://calculator.x-road.eu'>
    <SOAP-ENV:Header>
        <xroad:client id:objectType='SUBSYSTEM'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>generic-consumer</id:subsystemCode>
        </xroad:client>
        <xroad:service id:objectType='SERVICE'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>Calc</id:subsystemCode>
          <id:serviceCode>Add</id:serviceCode>
        </xroad:service>
        <xroad:id>411d6755661409fed365ad8135f8210be07613da</xroad:id>
        <xroad:protocolVersion>4.0</xroad:protocolVersion>
    </SOAP-ENV:Header>
        <SOAP-ENV:Body>
            <tns:ETTeavitus> 
            </tns:ETTeavitus>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope> 
            ";


            MemoryStream mss = new MemoryStream(Encoding.UTF8.GetBytes(xml));
            XteeSerializer serializer = new XteeSerializer();
            serializer.Deserialize<SoapEnvelope>(mss);

        }
        
        string xml = @"
    <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' 
                   xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
                   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
                   xmlns:xroad='http://x-road.eu/xsd/xroad.xsd'
                   xmlns:id = 'http://x-road.eu/xsd/identifiers'
                   xmlns:tns='http://calculator.x-road.eu'>
    <SOAP-ENV:Header>
        <xroad:client id:objectType='SUBSYSTEM'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>generic-consumer</id:subsystemCode>
        </xroad:client>
        <xroad:service id:objectType='SERVICE'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>Calc</id:subsystemCode>
          <id:serviceCode>Add</id:serviceCode>
          <id:serviceVersion>v2</id:serviceVersion>
        </xroad:service>
        <xroad:id>411d6755661409fed365ad8135f8210be07613da</xroad:id>
        <xroad:protocolVersion>4.0</xroad:protocolVersion>
    </SOAP-ENV:Header>
        <SOAP-ENV:Body>
            <tns:Add> 
                <request>
                    <VarX>1</VarX>
                    <VarY>2</VarY>
                </request>
            </tns:Add>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope> 
            ";

        string xml2 = @"
    <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' 
                   xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
                   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
                   xmlns:xroad='http://x-road.eu/xsd/xroad.xsd'
                   xmlns:id = 'http://x-road.eu/xsd/identifiers'
                   xmlns:tns='http://calculator.x-road.eu'>
    <SOAP-ENV:Header>
        <xroad:client id:objectType='SUBSYSTEM'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>generic-consumer</id:subsystemCode>
        </xroad:client>
        <xroad:service id:objectType='SERVICE'>
          <id:xRoadInstance>EE</id:xRoadInstance>
          <id:memberClass>GOV</id:memberClass>
          <id:memberCode>700030</id:memberCode>
          <id:subsystemCode>Calc</id:subsystemCode>
          <id:serviceCode>Add</id:serviceCode>
          <id:serviceVersion>v2</id:serviceVersion>
        </xroad:service>
        <xroad:id>411d6755661409fed365ad8135f8210be07613da</xroad:id>
        <xroad:protocolVersion>4.0</xroad:protocolVersion>
        <xroad:requestHash algorithmId='http://www.w3.org/2001/04/xmlenc#sha512'>W2G5s1zlu2PMTSFl4Vt8e5QHvp4P7H6gfE4ryhrcx69c4ah3CGmRPcjfcqm/aNaAP4qqp4IVFEEdRRhVFf2Jrw==</xroad:requestHash>
    </SOAP-ENV:Header>
        <SOAP-ENV:Body>
            <tns:AddResponse> 
                <request>
                    <VarX>1</VarX>
                    <VarY>2</VarY>
                </request>
                <Result>
                    <Value>3</Value>
                </Result>
            </tns:AddResponse>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope> 
            ";
        [Test]
        public void CalcEnvelopeTest()
        {
            MemoryStream mss = new MemoryStream(Encoding.UTF8.GetBytes(xml));
            var env = new XteeSerializer().Deserialize<SoapEnvelope>(mss);
            Assert.That(((AddRequest)env.Body).Request.VarX, Is.EqualTo(1));
            Assert.That(((AddInputHeader)env.Header).GetServiceName(), Is.EqualTo("EE.GOV.700030.Calc.Add.v2"));

        }

        [Test]
        public void ShouldBeAbleToDeserialiseResponseEnvelopeFromStream()
        {
            var mss = new MemoryStream(Encoding.UTF8.GetBytes(xml2));
            ISoapEnvelope obj =
            new XteeSerializer().Deserialize<SoapEnvelope>(mss);
            Assert.That(obj, Is.InstanceOf(typeof(SoapEnvelope)));
            var env = obj as SoapEnvelope;
            Assert.That(env.Header, Is.InstanceOf(typeof(AddOutputHeader)));
            Assert.That(env.Body, Is.InstanceOf(typeof(AddResponse)));

            var req = env.Body as AddResponse;
            Assert.That(req.Result.Value, Is.EqualTo(3));
            Assert.That(env.OperationName, Is.EqualTo("Add"));
            //Assert.That(((AddOutputHeader)env.Header).RequestHash == "http://www.w3.org/2001/04/xmlenc#sha512");
            Assert.That(((AddOutputHeader)env.Header).RequestHash == "W2G5s1zlu2PMTSFl4Vt8e5QHvp4P7H6gfE4ryhrcx69c4ah3CGmRPcjfcqm/aNaAP4qqp4IVFEEdRRhVFf2Jrw==");

        }

        [Test]
        [ExpectedException(ExpectedException = typeof(ArgumentException))]
        public void HeaderStreamGetsDisposed()
        {
            var headerStream = new MemoryStream(Encoding.UTF8.GetBytes("some text"));
            var soapEnvelope=new SoapEnvelope {HeaderStream = headerStream };

            soapEnvelope.Dispose();

            new StreamReader(headerStream);
            
        }
        
    }
}
